"""app"""
import os
from threading import Thread
from flask import Flask, g
import psycopg2
import redis
import httpx
import orjson
from loguru import logger
from applicaiton import hk_api, pdf_api, project_api, person_api, meet_api, tool_api, ranked_api
from util import handle_auth
app = Flask(__name__)

app.register_blueprint(pdf_api)
app.register_blueprint(person_api)
app.register_blueprint(hk_api)
app.register_blueprint(project_api)
app.register_blueprint(meet_api)
app.register_blueprint(tool_api)
app.register_blueprint(ranked_api)


REDIS_HOST = os.environ.get('REDIS_HOST', '172.16.173.210')
REDIS_PORT = os.environ.get('REDIS_PORT', 6379)
REDIS_PASSWORD = os.environ.get('REDIS_PASSWORD', 'Http://www.shuyo.cn')

app.config['DATABASE_URI'] = os.environ.get('DATABASE_URL', 'postgresql://gaussdb:zcpt123_#Shuyo@172.16.173.210:5433/postgres')

app.config['UPLOAD_FOLDER'] = os.environ.get('UPLOAD_FOLDER', 'static/upload/')
app.config['DOWNLOAD_FOLDER'] = os.environ.get('DOWNLOAD_FOLDER', 'static/download/')


app.config['TABLE_PROJECT'] = os.environ.get('TABLE_PROJECT', 'projects')
app.config['TABLE_PERSON'] = os.environ.get('TABLE_PERSON', 'persons')
app.config['TABLE_CABINET'] = os.environ.get('TABLE_CABINET', 'cabinet')
app.config['TABLE_PROJECT_PERSON_RELATION'] = os.environ.get('TABLE_PROJECT_PERSON_RELATION', 'project_person_relation')


app.config['CABINET_LOCK'] = os.environ.get('CABINET_LOCK', 'lock_')
app.config['CABINET_UNLOCK'] = os.environ.get('CABINET_UNLOCK', 'unlock_')
app.config['CABINET_DELETE'] = os.environ.get('CABINET_DELETE', 'delete_')
app.config['CABINET_EXPIRES'] = os.environ.get('CABINET_EXPIRES', 20)


# 初始化一些logger
logger.add("logs/error/file.log", format="{time:YYYY-MM-DD HH:mm:ss} {level} {message}", rotation="00:00", retention="30 days", enqueue=True, filter=lambda record: record["extra"].get("log_type") == "error")
logger.add("logs/lock/file.log", format="{time:YYYY-MM-DD HH:mm:ss} {level} {message}", rotation="00:00", retention="30 days", enqueue=True, filter=lambda record: record["extra"].get("log_type") == "lock")
logger.add("logs/unlock/file.log", format="{time:YYYY-MM-DD HH:mm:ss} {level} {message}", rotation="00:00", retention="30 days", enqueue=True, filter=lambda record: record["extra"].get("log_type") == "unlock")
logger.add("logs/delete/file.log", format="{time:YYYY-MM-DD HH:mm:ss} {level} {message}", rotation="00:00", retention="30 days", enqueue=True, filter=lambda record: record["extra"].get("log_type") == "delete")
logger.add("logs/signin/file.log", format="{time:YYYY-MM-DD HH:mm:ss} {level} {message}", rotation="00:00", retention="30 days", enqueue=True, filter=lambda record: record["extra"].get("log_type") == "signin")
logger.add("logs/signout/file.log", format="{time:YYYY-MM-DD HH:mm:ss} {level} {message}", rotation="00:00", retention="30 days", enqueue=True, filter=lambda record: record["extra"].get("log_type") == "signout")
logger.info("url", os.environ.get('foo'))

def connect_db():
    """创建数据库连接函数"""
    return psycopg2.connect(app.config['DATABASE_URI'])


def connect_redis():
    """创建 redis 连接函数"""
    connect = redis.ConnectionPool(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, decode_responses=True)
    return redis.StrictRedis(connection_pool=connect)


@app.before_request
def before_request():
    """在请求开始时连接数据库"""
  
    g.db_conn = connect_db()
    g.redis_conn = connect_redis()


@app.teardown_request
def teardown_request(exception):
    """在请求结束时关闭数据库连接"""
    if exception:
        logger.bind(log_type='error').error(exception)
    if hasattr(g, 'db_conn'):
        g.db_conn.close()
    if hasattr(g, 'redis_conn'):
        g.redis_conn.close()


def redis_ex_key_sub():
    """redis 监听key失效事件"""
    with app.app_context():
        pubsub = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, decode_responses=True).pubsub()
        # 发布监听key失效的订阅
        pubsub.psubscribe("__keyevent@*__:expired")
        # 通过无限循环等待事件
        for data in pubsub.listen():
            d = str(data["data"])
            if d.startswith(app.config['CABINET_LOCK']):

                parts = d.split("_")
                logger.bind(log_type='lock').info("🏒🏒🏒|" + ("-" * 50) + "|" + str(parts[1]) + "|" + ("-" * 50) + "|")
                params = {"position": str(parts[2]), "positionID": int(parts[3]), "row": int(parts[4]), "column": int(parts[5])}
                url = f'http://{parts[6]}/ISAPI/IntelligentCabinet/lockSpace?format=json'

                auth = handle_auth(url)
                res = httpx.put(url, data=orjson.dumps(params), auth=auth).json()
                
                logger.bind(log_type='lock').info(parts)
                logger.bind(log_type='lock').info(res)

            elif d.startswith(app.config['CABINET_UNLOCK']):
                parts = d.split("_")

                logger.bind(log_type='unlock').info("🏒🏒🏒|" + ("-" * 50) + "|" + str(parts[1]) + "|" + ("-" * 50) + "|")

                params = {"position": str(parts[2]), "positionID": int(parts[3]), "row": int(parts[4]), "column": int(parts[5])}
                url = f"http://{parts[6]}/ISAPI/IntelligentCabinet/unlockSpace?format=json"
                auth = handle_auth(url)
                res = httpx.put(url, data=orjson.dumps(params), auth=auth).json()
                
                logger.bind(log_type='unlock').info(parts)
                logger.bind(log_type='unlock').info(res)

            elif d.startswith(app.config['CABINET_DELETE']):
                parts = d.split("_")
                logger.bind(log_type='delete').info("🏒🏒🏒|" + ("-" * 50) + "|" + str(parts[1]) + "|" + ("-" * 50) + "|")
                url = f"http://{parts[2]}/ISAPI/AccessControl/UserInfo/Delete?format=json"
                auth = handle_auth(url)
                res = httpx.put(url, data=orjson.dumps({"UserInfoDelCond": {"EmployeeNoList": [{"employeeNo": parts[1]}]}}), auth=auth).json()
                
                logger.bind(log_type='delete').info(parts)
                logger.bind(log_type='delete').info(res)


if __name__ == '__main__':
    Thread(target=redis_ex_key_sub).start()
    app.run(host='0.0.0.0', port=5000)